package com.alibaba.citrus.cr.unified.inventory.functions.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.util.ThreadPoolUtil;
import com.alibaba.citrus.cr.unified.inventory.contants.FeaturesKey;
import com.alibaba.citrus.cr.unified.inventory.contants.UnifiedInventoryKey;
import com.alibaba.citrus.cr.unified.inventory.functions.service.AllocateOrderCloseService;
import com.alibaba.citrus.cr.unified.inventory.model.AllocateOrderEntity;
import com.alibaba.citrus.cr.unified.inventory.model.TransferOrderCloseDetail;
import com.alibaba.citrus.cr.unified.inventory.model.TransferOrderCloseRequest;
import com.alibaba.citrus.cr.unified.inventory.model.TransferOrderCloseResponse;
import com.alibaba.citrus.cr.unified.inventory.utils.CompareUtil;
import com.alibaba.citrus.cr.unified.inventory.utils.DictionaryConverter;
import com.alibaba.cloud.retail.delivery.api.model.delivery.enums.FulfillmentDirectionTypeEnum;
import com.alibaba.cloud.retail.delivery.api.model.delivery.request.fulfillment.BatchGetReq;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentDetailGetRes;
import com.alibaba.cloud.retail.delivery.api.model.delivery.response.fulfillment.FulfillmentGetRes;
import com.alibaba.cloud.retail.delivery.api.service.bcfulfillment.FulfillmentOrderAbilityService;
import com.alibaba.cloud.retail.wms.api.model.orders.common.WarehousingOrderDTO;
import com.alibaba.cloud.retail.wms.api.model.orders.common.WmsOrderDetailDTO;
import com.alibaba.cz.base.tool.FeatureUtil;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crforecastsales.dto.request.DictionaryQueryRequest;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.BatchQueryByCodeListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.BatchQueryDetailByAllocateOrderCodeListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.model.AllocateOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.service.AllocateOrderDetailService;
import com.epoch.app.crunifiedinventory.dto.request.AllocateOrderSyncRequest;
import com.epoch.app.crunifiedinventory.model.dto.AllocateOrderCloseDTO;
import com.epoch.app.crunifiedinventory.model.dto.AllocateOrderCloseRequest;
import com.epoch.app.crunifiedinventory.model.dto.AllocateOrderCloseResponse;
import com.epoch.app.crunifiedinventory.model.enums.AllocateOrderStatus;
import com.epoch.app.crunifiedinventory.model.enums.FulfillmentTypeEnum;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: yuhw
 * @date: 2024年03月07日 22:06
 **/
@Primary
@Service
public class AllocateOrderCloseServiceImpl implements AllocateOrderCloseService {

    private static Log log = Log.getLogger(AllocateOrderCloseServiceImpl.class);
    @Resource
    private AllocateOrderService allocateOrderService;
    @Resource
    private AllocateOrderDetailService allocateOrderDetailService;
    @DubboReference
    private FulfillmentOrderAbilityService fulfillmentOrderAbilityService;
    @Resource
    private AllocateOrderWriteService allocateOrderWriteService;
    @Resource
    private DictionaryConverter dictionaryConverter;

    private static final String FROM_SYS_GROUP = "fromSys";
    private static final String BUSINESS_TYPE_GROUP = "businessType";
    private static final String ALLOCATE_ORDER_TAG = "allocateOrderTag";
    private static final String CLOSE_REASON = "refuseReason";

    private static final List<Integer> CLOSEABLE_STATUS = Lists.newArrayList(
            AllocateOrderStatus.Shipment_Processing.getValue(), AllocateOrderStatus.Part_Shipped.getValue(),
            AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue(), AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue(),
            AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue(), AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue());


    @Override
    public Result<Boolean> closeAllocateOrder(AllocateOrderEntity current,
                                           List<AllocateOrderDetail> closeDetailList,
                                           List<WarehousingOrderDTO> warehousingOrderDTOList) {
        //找到本次关闭的行;
        //循环要关闭的明细
        if (CollectionUtils.isEmpty(closeDetailList)){
            return Result.success(true);
        }
        closeDetailList.forEach(closeDetail -> {
            if (AllocateOrderStatus.Shipment_Processing.getValue().equals(closeDetail.getStatus())){
                List<WmsOrderDetailDTO> matchedLines = Nullable.stream(warehousingOrderDTOList).map(WarehousingOrderDTO::getWmsOrderDetailList)
                        .filter(CollectionUtils::isNotEmpty)
                        .flatMap(Collection::stream)
                        .filter(d -> Objects.equals(d.getBizSubOrderId(), closeDetail.getLineNo() == null ? null : closeDetail.getLineNo().toString()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(matchedLines)){
                    closeDetail.setStatus(AllocateOrderStatus.Cancel.getValue());
                }
            }else if (CompareUtil.anyOf(closeDetail.getStatus(),AllocateOrderStatus.DRAFT.getValue(),AllocateOrderStatus.WAIT_PUSH.getValue())){
                closeDetail.setStatus(AllocateOrderStatus.Cancel.getValue());
            }else if (CompareUtil.anyOf(closeDetail.getStatus(),AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue(),AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue(),
                    AllocateOrderStatus.PART_SHIPPED_RECEIVED.getValue())){
                Map<String, String> featuresMap = FeatureUtil.fromString(closeDetail.getBizFeatures());
                String receivedQuantity = featuresMap.getOrDefault(FeaturesKey.CUMULATIVE_RECEIVED_QUANTITY, BigDecimal.ZERO.toString());
                String deliveryQuantity = featuresMap.getOrDefault(FeaturesKey.CUMULATIVE_DELIVERY_QUANTITY, BigDecimal.ZERO.toString());
                if (new BigDecimal(receivedQuantity).compareTo(new BigDecimal(deliveryQuantity)) < 0){
                    if (AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.ALL_SHIPPED_NONE_RECEIVED.getValue());
                    }else if (AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue());
                    }else if (AllocateOrderStatus.PART_SHIPPED_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.COMPLETED.getValue());
                    }
                }else if (new BigDecimal(receivedQuantity).compareTo(new BigDecimal(deliveryQuantity)) == 0){
                    closeDetail.setStatus(AllocateOrderStatus.COMPLETED.getValue());
                }
            }else if (CompareUtil.anyOf(closeDetail.getStatus(),AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue(),
                    AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue(),AllocateOrderStatus.PART_SHIPPED_YARD_RECEIVED.getValue())){
                Map<String, String> featuresMap = FeatureUtil.fromString(closeDetail.getBizFeatures());
                String receivedQuantity = featuresMap.getOrDefault(FeaturesKey.CUMULATIVE_RECEIVED_QUANTITY, BigDecimal.ZERO.toString());
                String deliveryQuantity = featuresMap.getOrDefault(FeaturesKey.CUMULATIVE_DELIVERY_QUANTITY, BigDecimal.ZERO.toString());
                if (new BigDecimal(receivedQuantity).compareTo(new BigDecimal(deliveryQuantity)) < 0){
                    if (AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue());
                    }else if (AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue());
                    }else if (AllocateOrderStatus.PART_SHIPPED_YARD_RECEIVED.getValue().equals(closeDetail.getStatus())){
                        closeDetail.setStatus(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue());
                    }
                }else if (new BigDecimal(receivedQuantity).compareTo(new BigDecimal(deliveryQuantity)) == 0){
                    closeDetail.setStatus(AllocateOrderStatus.COMPLETED.getValue());
                }
            }
            allocateOrderDetailService.updateAllocateOrderDetail(closeDetail);
            //已取消, 已完成 保持不变
            log.info("closeDetail:{}",JSON.toJSONString(closeDetail.getStatus()));
        });
        //TODO 需要有一个通用的推进状态方法
        AllocateOrderDetailLoadListRequest loadListRequest  = new AllocateOrderDetailLoadListRequest();
        loadListRequest.setAllocateOrderCode(closeDetailList.get(0).getAllocateOrderCode());
        loadListRequest.setLimit(1000);
        Result<List<AllocateOrderDetail>> detailListResult = allocateOrderDetailService.loadAllocateOrderDetailList(loadListRequest);
        if (detailListResult != null && CollectionUtils.isNotEmpty(detailListResult.getResult())){
            log.info("calculateMainOrderStatus_request:{}",JSON.toJSONString(detailListResult));
            Integer mainOrderStatus = calculateMainOrderStatus(detailListResult.getResult());
            log.info("calculateMainOrderStatus_result:{}",JSON.toJSONString(mainOrderStatus));
            AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
            allocateOrderLoadListRequest.setCode(closeDetailList.get(0).getAllocateOrderCode());
            Result<List<AllocateOrder>> allocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
            if (mainOrderStatus != null && allocateOrderList != null && CollectionUtils.isNotEmpty(allocateOrderList.getResult())){
                AllocateOrder allocateOrder = allocateOrderList.getResult().get(0);
                allocateOrder.setStatus(mainOrderStatus);
                allocateOrderService.updateAllocateOrder(allocateOrder);
            }
        }
        return Result.success(true);
    }

    @Override
    public Result<TransferOrderCloseResponse> closeAllocateOrder(TransferOrderCloseRequest transferOrderCloseRequest) {
        String errorMessage = checkTransferOrderCloseRequest(transferOrderCloseRequest);
        if(StringUtils.isNotEmpty(errorMessage))

        {
            return Result.fail("OTS-05-001-10-16-001", errorMessage);
        }

        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|enter|request={}",JSON.toJSONString(transferOrderCloseRequest));

        List<TransferOrderCloseDetail> closeList = transferOrderCloseRequest.getCloseList();

        // 去重
        List<TransferOrderCloseDetail> filteredList = new ArrayList<>(closeList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        detail -> detail.getTransferOrderCode() + "@" + detail.getDetailNo(),
                        Function.identity(),
                        (v1, v2) -> v1))
                .values());

        if(filteredList.size()!=closeList.size())

        {
            return Result.fail("OTS-05-001-10-16-001", "关闭列表明细不能重复");
        }

        // 批量查询
        List<String> allocateOrderCodeList = filteredList.stream().map(TransferOrderCloseDetail::getTransferOrderCode).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        // 主单
        Result<List<AllocateOrder>> orderListResult = allocateOrderService.batchQueryByCodeList(BatchQueryByCodeListRequest.builder().codeList(allocateOrderCodeList).build());
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryAllocateOrder|code={}|result={}",JSON.toJSONString(allocateOrderCodeList),JSON.toJSONString(orderListResult));
        List<AllocateOrder> orderList = orderListResult.getResult();
        if(CollectionUtils.isEmpty(orderList))

        {
            filteredList.forEach(detail -> {
                detail.setSuccess(Boolean.FALSE);
                detail.setErrorCode("OTS-05-001-10-17-001");
                detail.setErrorMessage("该调拨单不存在");
            });
            TransferOrderCloseResponse response = new TransferOrderCloseResponse(filteredList);
            return Result.success(response);
        }

        Map<String, AllocateOrder> orderCodeMap = orderList.stream().filter(Objects::nonNull)
                .collect(Collectors.toMap(AllocateOrder::getCode, Function.identity(), (v1, v2) -> v1));

        // 子单，根据主单号分组
        Result<List<AllocateOrderDetail>> detailListResult = allocateOrderDetailService.batchQueryDetailByAllocateOrderCodeList(BatchQueryDetailByAllocateOrderCodeListRequest
                .builder().allocateOrderCodeList(allocateOrderCodeList).build());
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryAllocateDetail|code={}|result={}",JSON.toJSONString(allocateOrderCodeList),JSON.toJSONString(detailListResult));
        List<AllocateOrderDetail> details = detailListResult.getResult();
        if(CollectionUtils.isEmpty(details))

        {
            filteredList.forEach(detail -> {
                detail.setSuccess(Boolean.FALSE);
                detail.setErrorCode("OTS-05-001-10-17-001");
                detail.setErrorMessage("该调拨单不存在该行");
            });
        }

        // key: 主单号，value: key: 行号，value: 子单
        Map<String, Map<String, AllocateOrderDetail>> detailMap = details.stream()
                .collect(Collectors.groupingBy(
                        AllocateOrderDetail::getAllocateOrderCode,
                        Collectors.toMap(
                                detail -> detail.getLineNo().toString(),
                                detail -> detail
                        )
                ));

        // 履约单，需要先从调拨单的feature上取
        List<String> forwardFulfillmentNoList = orderList.stream().filter(Objects::nonNull).map(AllocateOrder::getFeatures).filter(StringUtils::isNotBlank)
                .distinct().map(FeatureUtil::fromString).filter(MapUtils::isNotEmpty).map(feature -> feature.get("forwardFulfillmentOrderNo"))
                .filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());

        // 批量查询履约单
        Map<String, FulfillmentGetRes> fulfillmentNoMap = new HashMap<>();
        if(CollectionUtils.isNotEmpty(forwardFulfillmentNoList))

        {
            BatchGetReq batchGetReq = new BatchGetReq();
            batchGetReq.setFulfillmentOrderNoList(forwardFulfillmentNoList);
            batchGetReq.setFulfillmentDirectionType(FulfillmentDirectionTypeEnum.FORWARD.getValue());
            com.alibaba.cloud.retail.delivery.api.model.delivery.response.Result<List<FulfillmentGetRes>> fulfillmentResult = fulfillmentOrderAbilityService.batchGet(batchGetReq);
            log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|queryFulfillment|request={}|result={}", JSON.toJSONString(batchGetReq), JSON.toJSONString(fulfillmentResult));
            if (CollectionUtils.isNotEmpty(fulfillmentResult.getResult())) {
                fulfillmentNoMap = fulfillmentResult.getResult().stream().filter(Objects::nonNull)
                        .collect(Collectors.toMap(FulfillmentGetRes::getFulfillmentOrderNo, Function.identity()));
            }
        }

        List<TransferOrderCloseDetail> resultList = new ArrayList<>();
        List<TransferOrderCloseDetail> toCloseList = new ArrayList<>();
        for(
                TransferOrderCloseDetail transferOrderCloseDetail :filteredList)

        {
            String transferOrderCode = transferOrderCloseDetail.getTransferOrderCode();
            String detailNo = transferOrderCloseDetail.getDetailNo();

            AllocateOrder allocateOrder = orderCodeMap.get(transferOrderCode);

            if (allocateOrder == null) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            //【判断一：履约方式】履约方式为大仓发货，大仓收货，虚拟移库之一，其他履约方式代表由SAP发起后并同步中台，需在SAP中操作关闭后通过集成接口同步中台。
            if (!FulfillmentTypeEnum.PILOT2PILOT.getValue().toString().equals(allocateOrder.getFulfillmentTypeCode())
                    && !FulfillmentTypeEnum.VIRTUAL_TRANSFER.getValue().toString().equals(allocateOrder.getFulfillmentTypeCode())) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-002");
                transferOrderCloseDetail.setErrorMessage("履约方式为大仓发货大仓收货，虚拟移库才可以关闭调拨单");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            // 【判断二：调拨子单状态】子单状态为待发货,部分发货，未收货部分发货，部分收货部分发货，货场仓未收货部分发货，货场部分收货之一才允许关闭。
            Map<String, AllocateOrderDetail> detailLineMap = detailMap.get(transferOrderCode);
            if (MapUtils.isEmpty(detailLineMap)) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            AllocateOrderDetail allocateOrderDetail = detailLineMap.get(detailNo);

            if (allocateOrderDetail == null) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-001");
                transferOrderCloseDetail.setErrorMessage("该调拨单不存在这一行");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            if (!CLOSEABLE_STATUS.contains(allocateOrderDetail.getStatus())) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-003");
                transferOrderCloseDetail.setErrorMessage("调拨子单状态非法");
                resultList.add(transferOrderCloseDetail);
                continue;
            }
            transferOrderCloseDetail.setDetailId(allocateOrderDetail.getId());
            transferOrderCloseDetail.setStatus(allocateOrderDetail.getStatus());

            // 【判断三：关联的履约子单状态】根据【调拨单号+行号】查询所关联的【正向履约单明细行】
            //      a. 若查询不到，则允许关闭。
            String bizFeatures = allocateOrder.getFeatures();
            Map<String, String> featureMap = FeatureUtil.fromString(bizFeatures);
            if (MapUtils.isEmpty(featureMap) || StringUtils.isEmpty(featureMap.get("forwardFulfillmentOrderNo"))) {
                toCloseList.add(transferOrderCloseDetail);
                continue;
            }

            String fulfillmentOrderCode = featureMap.get("forwardFulfillmentOrderNo");

            FulfillmentGetRes fulfillmentRes = fulfillmentNoMap.get(fulfillmentOrderCode);
            if (fulfillmentRes == null) {
                toCloseList.add(transferOrderCloseDetail);
                continue;
            }

            // 能查询到履约单和子单
            List<FulfillmentDetailGetRes> detailList = fulfillmentRes.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
                transferOrderCloseDetail.setErrorMessage("履约单没有明细行");
                resultList.add(transferOrderCloseDetail);
                continue;
            }

            Map<String, FulfillmentDetailGetRes> fulfillmentOrderDetailMap = detailList.stream().collect(Collectors.toMap(FulfillmentDetailGetRes::getRefOrderLineNo, Function.identity(), (v1, v2) -> v1));
            FulfillmentDetailGetRes fulfillmentOrderDetail = fulfillmentOrderDetailMap.get(detailNo);
            // b. 若能查询到，且所查询到的所有正向履约单明细行的状态都为【已取消】或【已完成】时，且累加的【已出库数量】小于【调拨单数量】

            if (fulfillmentOrderDetail != null) {
                // 7: 已取消，8:已完成
//                List<String> allowedStatus = Lists.newArrayList("7", "8");
//                if (!allowedStatus.contains(fulfillmentOrderDetail.getStatus())) {
//                    transferOrderCloseDetail.setSuccess(Boolean.FALSE);
//                    transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
//                    transferOrderCloseDetail.setErrorMessage("履约单明细行的状态不是已取消或已完成");
//                    resultList.add(transferOrderCloseDetail);
//                    continue;
//                }
                BigDecimal shippedQuantity = fulfillmentOrderDetail.getShippedQuantity();
                String quantity = allocateOrderDetail.getQuantity();
                if (StringUtils.isEmpty(quantity)) {
                    transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                    transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-006");
                    transferOrderCloseDetail.setErrorMessage("调拨单行上的数量为空");
                    resultList.add(transferOrderCloseDetail);
                    continue;
                }
                if (shippedQuantity != null) {
                    BigDecimal allocateOrderQuantity = new BigDecimal(quantity);
                    int compare = shippedQuantity.compareTo(allocateOrderQuantity);
                    if (compare >= 0) {
                        transferOrderCloseDetail.setSuccess(Boolean.FALSE);
                        transferOrderCloseDetail.setErrorCode("OTS-05-001-10-17-007");
                        transferOrderCloseDetail.setErrorMessage("无法关闭，已出库数量不小于调拨单数量");
                        resultList.add(transferOrderCloseDetail);
                        continue;
                    }
                }
                // 已发货数量等于已收货数量，调拨单明细状态应推进到已完成或已发货，货场仓已收货
                Integer receiveQuantity = allocateOrderDetail.getReceiveQuantity();
                if (shippedQuantity != null && receiveQuantity != null) {
                    BigDecimal receiveQuantityNum = new BigDecimal(receiveQuantity);
                    if (shippedQuantity.compareTo(receiveQuantityNum) == 0) {
                        Integer originStatus = transferOrderCloseDetail.getStatus();
                        transferOrderCloseDetail.setStatus(originStatus + UnifiedInventoryKey.PART_RECEIVE_2_COMPLETE_VALUE);
                    }
                }

            }
            toCloseList.add(transferOrderCloseDetail);
        }

        // 取消
        AllocateOrderCloseRequest request = new AllocateOrderCloseRequest();
        String operatorId = transferOrderCloseRequest.getOperatorId();
        request.setOperatorId(operatorId);
        request.setCloseList(toCloseList.stream().

                map(detail ->

                {
                    AllocateOrderCloseDTO dto = new AllocateOrderCloseDTO();
                    BeanUtils.copyProperties(detail, dto);
                    dto.setOperatorId(operatorId);
                    AllocateOrder allocateOrder = orderCodeMap.get(detail.getTransferOrderCode());
                    if (allocateOrder == null) {
                        return dto;
                    }
                    dto.setOutAllocateOrderId(allocateOrder.getOutAllocateOrderId());
                    Map<String, AllocateOrderDetail> stringAllocateOrderDetailMap = detailMap.get(detail.getTransferOrderCode());
                    if (MapUtils.isEmpty(stringAllocateOrderDetailMap)) {
                        return dto;
                    }
                    AllocateOrderDetail allocateOrderDetail = stringAllocateOrderDetailMap.get(detail.getDetailNo());
                    if (allocateOrderDetail == null) {
                        return dto;
                    }
                    dto.setOutAllocateOrderLineNo(allocateOrderDetail.getOutAllocateOrderLineId());
                    return dto;
                }).

                collect(Collectors.toList()));
        AllocateOrderCloseResponse closeResponse = allocateOrderWriteService.closeAllocateOrder(request);
        log.info("TransferOrderWriteServiceImpl|closeAllocateOrder|close|request={}|response={}",JSON.toJSONString(request),JSON.toJSONString(closeResponse));

        if(CollectionUtils.isNotEmpty(closeResponse.getResultList()))

        {
            resultList.addAll(closeResponse.getResultList().stream().map(dto -> {
                TransferOrderCloseDetail detail = new TransferOrderCloseDetail();
                detail.setErrorCode(dto.getErrorCode());
                detail.setErrorMessage(dto.getErrorMessage());
                detail.setTransferOrderCode(dto.getTransferOrderCode());
                detail.setDetailNo(dto.getDetailNo());
                detail.setSuccess(dto.getSuccess());
                return detail;
            }).collect(Collectors.toList()));
        }

        // 异步校验是否需要修改主单状态
        Set<TransferOrderCloseDetail> closedSet = resultList.stream().filter(Objects::nonNull).filter(detail -> Boolean.TRUE.equals(detail.getSuccess())).collect(Collectors.toSet());
        if(CollectionUtils.isNotEmpty(closedSet))

        {
            for (TransferOrderCloseDetail detail : closedSet) {
                ThreadPoolUtil.execute(() -> {
                    try {
                        checkAndPushAllocateOrderStatus(detail, operatorId);
                    } catch (Throwable t) {
                        log.error("TransferOrderWriteService|closeAllocateOrder|checkAndPushAllocateOrderStatus|error|resultList={}", resultList, t);
                    }
                });
            }
        }

        resultList.forEach(result ->

        {
            result.setDetailId(null);
            result.setStatus(null);
            result.setCloseCode(null);
        });

        TransferOrderCloseResponse response = new TransferOrderCloseResponse(resultList);
        return Result.success(response);

    }

    private void checkAndPushAllocateOrderStatus(TransferOrderCloseDetail closeDetail, String operatorId) {
        if (closeDetail == null) {
            return;
        }


        AllocateOrderDetailLoadListRequest queryRequest = AllocateOrderDetailLoadListRequest.newAllocateOrderDetailLoadListRequestBuilder().allocateOrderCode(closeDetail.getTransferOrderCode()).build();
        queryRequest.setSize(1000);
        Result<List<AllocateOrderDetail>> detailListResult = allocateOrderDetailService.loadAllocateOrderDetailList(queryRequest);
        if (CollectionUtils.isEmpty(detailListResult.getResult())) {
            return;
        }

        List<AllocateOrderDetail> detailList = detailListResult.getResult();
        // 计算主单状态
        Integer mainOrderStatus = calculateMainOrderStatus(detailList);

        AllocateOrderLoadListRequest queryOrderRequest = AllocateOrderLoadListRequest.newAllocateOrderLoadListRequestBuilder().code(closeDetail.getTransferOrderCode()).build();
        Result<List<AllocateOrder>> listResult = allocateOrderService.loadAllocateOrderList(queryOrderRequest);
        AllocateOrder allocateOrder = listResult.getResult().get(0);
        if (allocateOrder == null) {
            return;
        }
        if (mainOrderStatus != null && !Objects.equals(allocateOrder.getStatus(), mainOrderStatus)) {
            allocateOrder.setStatus(mainOrderStatus);
            allocateOrder.setOperatorId(operatorId);
            allocateOrderService.updateAllocateOrder(allocateOrder);
        }

    }

    private Integer calculateMainOrderStatus(List<AllocateOrderDetail> subOrders) {
        // 检查子单是否全部为已取消
        if (allSubOrdersHaveStatus(subOrders, AllocateOrderStatus.Cancel.getValue())) {
            return AllocateOrderStatus.Cancel.getValue();
        }

        subOrders.removeAll(subOrders.stream().filter(subOrder -> AllocateOrderStatus.Cancel.getValue().equals(subOrder.getStatus())).collect(Collectors.toList()));

        if (subOrders.size() == 1) {
            return subOrders.get(0).getStatus();
        }

        // 检查子单是否全部为已完成
        if (allSubOrdersHaveStatus(subOrders, AllocateOrderStatus.COMPLETED.getValue())) {
            return AllocateOrderStatus.COMPLETED.getValue();
        }

        // 检查子单是否包含部分发货状态
        boolean containsPartialShipment = subOrders.stream().anyMatch(detail ->
                detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                        detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
        );

        // 根据子单状态计算主单状态
        if (containsPartialShipment) {
            // 判断是否包含"货场仓"
            boolean containsYard = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            // 判断是否包含"部分收货"
            boolean containsPartReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            // 根据是否包含"货场仓"和"部分收货"返回相应状态
            if (containsYard) {
                return containsPartReceived ? AllocateOrderStatus.PART_SHIPPED_YARD_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.PART_SHIPPED_YARD_NONE_RECEIVED.getValue();
            } else {
                return containsPartReceived ? AllocateOrderStatus.PART_SHIPPED_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.PART_SHIPPED_NONE_RECEIVED.getValue();
            }
        }

        // 检查子单是否包含已发货状态且不包含部分发货状态
        boolean containsShipmentWithoutPartial = subOrders.stream().anyMatch(detail ->
                detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_NONE_RECEIVED.getValue())
                        || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue())
                        || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue())
                        || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue())
                        || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue())
                        || detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue())
        );

        if (containsShipmentWithoutPartial) {
            // 判断是否包含"货场仓"
            boolean containsYard = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue())
            );

            // 判断是否包含"部分收货"
            boolean containsPartReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue()) ||
                            detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue())
            );

            boolean containsPartFinalFinished = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue()));

            boolean containsYardReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue()));


            boolean containsYardNoneReceived = subOrders.stream().anyMatch(detail ->
                    detail.getStatus().equals(AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue()));
            // 根据是否包含"货场仓"和"部分收货"返回相应状态
            if (containsYard) {
                if (containsPartReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_PART_RECEIVED.getValue();
                } else if (containsPartFinalFinished) {
                    return AllocateOrderStatus.ALL_SHIPPED_PART_FINAL_RECEIVED.getValue();
                } else if (containsYardReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_RECEIVED.getValue();
                } else if (containsYardNoneReceived) {
                    return AllocateOrderStatus.ALL_SHIPPED_YARD_NONE_RECEIVED.getValue();
                }
            } else {
                return containsPartReceived ? AllocateOrderStatus.ALL_SHIPPED_PART_RECEIVED.getValue() :
                        AllocateOrderStatus.ALL_SHIPPED_NONE_RECEIVED.getValue();
            }
        }

        // 默认情况
        return null;
    }

    private boolean allSubOrdersHaveStatus(List<AllocateOrderDetail> subOrders, Integer status) {
        return subOrders.stream().allMatch(detail -> detail.getStatus().equals(status));
    }

    private String checkTransferOrderCloseRequest(TransferOrderCloseRequest transferOrderCloseRequest) {
        if (StrUtil.isBlank(transferOrderCloseRequest.getFromSys())){
            return "来源系统不能为空";
        }
        if (transferOrderCloseRequest.getFromSys().length()>16){
            return "来源系统长度不能超过16";
        }
        if (!checkDictionary(FROM_SYS_GROUP,transferOrderCloseRequest.getFromSys())){
            return "来源系统非法";
        }
        if (StrUtil.isBlank(transferOrderCloseRequest.getBusinessType())){
            return "业态不能为空";
        }
        if (transferOrderCloseRequest.getBusinessType().length()>16){
            return "业态长度不能超过16";
        }
        if (!checkDictionary(BUSINESS_TYPE_GROUP,transferOrderCloseRequest.getBusinessType())){
            return "业态非法";
        }
        if (StringUtils.isBlank(transferOrderCloseRequest.getOperatorId())) {
            return "修改人不能为空";
        }
        if (transferOrderCloseRequest.getOperatorId().length() > 32) {
            return "修改人长度不能超过32";
        }
        List<TransferOrderCloseDetail> closeList = transferOrderCloseRequest.getCloseList();
        if (CollectionUtils.isEmpty(closeList)) {
            return "关闭列表不能为空";
        }
        if (closeList.size() > 100) {
            return "关闭列表的元素数量不能超过100";
        }
        for (TransferOrderCloseDetail detail : closeList) {
            if (StringUtils.isBlank(detail.getTransferOrderCode())) {
                return "调拨单号不能为空";
            }
            if (detail.getTransferOrderCode().length() > 32) {
                return "调拨单号长度不能超过32";
            }
            if (StringUtils.isBlank(detail.getDetailNo())) {
                return "调拨单行号不能为空";
            }
            if (detail.getDetailNo().length() > 32) {
                return "调拨单行号长度不能超过32";
            }
            if (StringUtils.isNotBlank(detail.getCloseCode())) {
                String closeCode = detail.getCloseCode();
                if (closeCode.length() > 32) {
                    return "关闭原因编码长度不能超过32";
                }
            }
        }

        List<String> closeCodeList = closeList.stream().map(TransferOrderCloseDetail::getCloseCode).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(closeCodeList)) {
            for (String closeCode : closeCodeList) {
                if (!checkDictionary(CLOSE_REASON,closeCode)) {
                    return "关闭原因编码不合法";
                }
            }
        }

        return null;
    }

    /**
     * 校验字典
     * @param group
     * @param code
     * @return
     */
    private boolean checkDictionary(String group, String code) {
        return dictionaryConverter.checkDictionaryCode(group,code);
//        DictionaryQueryRequest request = new DictionaryQueryRequest();
//        request.setGroup(group);
//        Result<List<DictionaryResponse>> result = mnInventoryCenterService.queryDictionaryDataListApi(request);
//        Set<String> businessTypeSet = result.getResult().stream()
//                .map(DictionaryResponse::getCode)
//                .collect(Collectors.toSet());
//        return businessTypeSet.contains(code);
    }
}
